Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0007178OCamlstandard librarypublic2016-03-11 18:382018-05-17 13:25
Reporterdbuenzli 
Assigned To 
PrioritynormalSeverityminorReproducibilityhave not tried
StatusacknowledgedResolutionopen 
PlatformOSOS Version
Product Version4.02.3 
Target VersionFixed in Version 
Summary0007178: Calling exit in at_exit callback results in infinite loop.
DescriptionE.g. in C the following program will exit with 1.

#include <stdio.h>
#include <stdlib.h>

void do_exit (void)
{
  puts ("Goodbye, world!\n");
  exit (1);
}

int main (int argc, char *argv[])
{
  atexit (do_exit);
  puts ("Hello, world!\n");
  return 0;
}

Steps To Reproduceocaml
# at_exit (fun () -> exit 1);;
- : unit = ()
# ^D
Fatal error: exception Stack overflow
Raised by primitive operation at file "pervasives.ml", line 515, characters 30-3
TagsNo tags attached.
Attached Files

- Relationships
related to 0007796confirmed "at_exit" function run twice with cleanup-at-exit runtime option 

-  Notes
(0015481)
shinwell (developer)
2016-03-14 09:21

According to "man atexit" on my system, the POSIX.1-2001 behaviour of calling exit within an atexit handler is undefined. Indeed it suggests an infinite loop is a possible outcome. I think the correct way of exiting from an atexit function is probably to call _exit.
(0015484)
dbuenzli (reporter)
2016-03-14 10:42

Indeed http://pubs.opengroup.org/onlinepubs/9699919799/functions/atexit.html [^] requires from an atexit function either to return or to call _exit or "a function that causes abnormal termination". So a binding to _exit or abort (preferably the former) would be nice.
(0015912)
dbuenzli (reporter)
2016-05-10 11:48
edited on: 2016-05-10 11:50

Note that this is not a binding issue since everything is handled in OCaml land. If we leave threading issues aside, the at_exit function here:

https://github.com/ocaml/ocaml/blob/393f068a1d4e0b267012b10aac822d11160a7cfd/stdlib/pervasives.ml#L519-L521 [^]

let exit retcode =
  do_at_exit ();
  sys_exit retcode

Could be replaced by:

let exit_code = ref None
let exit retcode = match !exit_code with
| Some _ when retcode = 0 -> ()
| Some _ -> exit_code := Some retcode
| None ->
  exit_code := Some retcode;
  do_at_exit ();
  match !exit_code with
  | None -> assert false
  | Some retcode -> sys_exit retcode

to solve the problem. The semantics is that the last non-zero [exit] call gives the final exit code of the program.

(0016047)
dbuenzli (reporter)
2016-07-07 22:55

Fix in https://github.com/ocaml/ocaml/pull/675 [^]

Basically along the lines mentioned above except I had to introduce an exception because exit's signature is int -> 'a, not int -> unit as the code above assumed.

- Issue History
Date Modified Username Field Change
2016-03-11 18:38 dbuenzli New Issue
2016-03-14 09:21 shinwell Note Added: 0015481
2016-03-14 10:42 dbuenzli Note Added: 0015484
2016-03-24 19:08 doligez Status new => acknowledged
2016-03-24 19:08 doligez Target Version => 4.03.1+dev
2016-05-10 11:48 dbuenzli Note Added: 0015912
2016-05-10 11:50 dbuenzli Note Edited: 0015912 View Revisions
2016-07-07 22:55 dbuenzli Note Added: 0016047
2017-02-16 14:00 doligez Target Version 4.03.1+dev => undecided
2017-02-23 16:43 doligez Category OCaml standard library => standard library
2017-04-10 14:51 doligez Target Version undecided =>
2018-05-17 13:25 xleroy Relationship added related to 0007796


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker