The go c-shared object need the libc to pass them
the argc and argv parameters in order to initialize
the runtime properly.

This is a preparation patch for this.

Since I like to be able to seemlingly prove code move
in my head this make use of a lot of class variables
that I will get rid of in next patches.

Signed-off-by: Benoît Canet <ben...@scylladb.com>
---
 core/app.cc        | 65 ++++++++++++++++++++++++++++--------------------------
 include/osv/app.hh |  8 +++++++
 2 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/core/app.cc b/core/app.cc
index ad3145f..515096e 100644
--- a/core/app.cc
+++ b/core/app.cc
@@ -294,20 +294,31 @@ void application::main()
     // _entry_point() doesn't return
 }
 
-void application::run_main(std::string path, int argc, char** argv)
+void application::prepare_argc_argv()
 {
-    char *c_path = (char *)(path.c_str());
+    // C main wants mutable arguments, so we have can't use strings directly
+    transform(_args, back_inserter(_mut_args),
+            [](std::string s) { return std::vector<char>(s.data(), s.data() + 
s.size() + 1); });
+    std::vector<char*> argv;
+    transform(_mut_args.begin(), _mut_args.end(), back_inserter(argv),
+            [](std::vector<char>& s) { return s.data(); });
+    _argc = argv.size();
+    argv.push_back(nullptr);
+
+    char **argv_data = argv.data();
+
+    char *c_path = (char *)(_command.c_str());
     // path is guaranteed to keep existing this function
     program_invocation_name = c_path;
     program_invocation_short_name = basename(c_path);
 
-    auto sz = argc; // for the trailing 0's.
-    for (int i = 0; i < argc; ++i) {
-        sz += strlen(argv[i]);
+    auto sz = _argc; // for the trailing 0's.
+    for (int i = 0; i < _argc; ++i) {
+        sz += strlen(argv_data[i]);
     }
 
-    std::unique_ptr<char []> argv_buf(new char[sz]);
-    char *ab = argv_buf.get();
+    _argv_buf.reset(new char[sz]);
+    char *ab = _argv_buf.get();
     // In Linux, the pointer arrays argv[] and envp[] are continguous.
     // Unfortunately, some programs rely on this fact (e.g., libgo's
     // runtime_goenvs_unix()) so it is useful that we do this too.
@@ -315,44 +326,36 @@ void application::run_main(std::string path, int argc, 
char** argv)
     while (environ[envcount]) {
         envcount++;
     }
-    char *contig_argv[argc + 1 + envcount + 1];
+    _contig_argv.reset(new char*[_argc + 1 + envcount + 1]);
+    char **contig_argv = _contig_argv.get();
 
-    for (int i = 0; i < argc; ++i) {
-        size_t asize = strlen(argv[i]);
-        memcpy(ab, argv[i], asize);
+    for (int i = 0; i < _argc; ++i) {
+        size_t asize = strlen(argv_data[i]);
+        memcpy(ab, argv_data[i], asize);
         ab[asize] = '\0';
         contig_argv[i] = ab;
         ab += asize + 1;
     }
-    contig_argv[argc] = nullptr;
+    contig_argv[_argc] = nullptr;
 
     for (int i = 0; i < envcount; i++) {
-        contig_argv[argc + 1 + i] = environ[i];
+        contig_argv[_argc + 1 + i] = environ[i];
     }
-    contig_argv[argc + 1 + envcount] = nullptr;
-
-    // make sure to have a fresh optind across calls
-    // FIXME: fails if run() is executed in parallel
-    int old_optind = optind;
-    optind = 0;
-    _return_code = _main(argc, contig_argv);
-    optind = old_optind;
+    contig_argv[_argc + 1 + envcount] = nullptr;
 }
 
 void application::run_main()
 {
     trace_app_main(this, _command.c_str());
 
-    // C main wants mutable arguments, so we have can't use strings directly
-    std::vector<std::vector<char>> mut_args;
-    transform(_args, back_inserter(mut_args),
-            [](std::string s) { return std::vector<char>(s.data(), s.data() + 
s.size() + 1); });
-    std::vector<char*> argv;
-    transform(mut_args.begin(), mut_args.end(), back_inserter(argv),
-            [](std::vector<char>& s) { return s.data(); });
-    auto argc = argv.size();
-    argv.push_back(nullptr);
-    run_main(_command, argc, argv.data());
+    prepare_argc_argv();
+
+    // make sure to have a fresh optind across calls
+    // FIXME: fails if run() is executed in parallel
+    int old_optind = optind;
+    optind = 0;
+    _return_code = _main(_argc, _contig_argv.get());
+    optind = old_optind;
 
     if (_return_code) {
         debug("program %s returned %d\n", _command.c_str(), _return_code);
diff --git a/include/osv/app.hh b/include/osv/app.hh
index 6fa503a..3ecf1a8 100644
--- a/include/osv/app.hh
+++ b/include/osv/app.hh
@@ -194,6 +194,7 @@ private:
     void start_and_join(waiter* setup_waiter);
     void main();
     void run_main(std::string path, int argc, char** argv);
+    void prepare_argc_argv();
     void run_main();
     friend void ::__libc_start_main(int(*)(int, char**), int, char**, 
void(*)(),
         void(*)(), void(*)(), void*);
@@ -214,6 +215,13 @@ private:
     void (*_entry_point)();
     static app_registry apps;
 
+    // argc and argv variables
+    std::vector<std::vector<char>> _mut_args;
+    std::unique_ptr<char *> _contig_argv;
+    std::unique_ptr<char []> _argv_buf;
+    std::vector<char*> _argv;
+    int _argc;
+
     // Must be destroyed before _lib, because contained function objects may
     // have destructors which are part of the application's code.
     std::list<std::function<void()>> _termination_request_callbacks;
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to